package drds.configuration.db.xml_mapping.annotation.dto;


import drds.configuration.db.xml_mapping.MapperFactory;
import drds.configuration.db.xml_mapping.configuration.ParameterMap;
import drds.configuration.db.xml_mapping.configuration.ParameterMapping;
import drds.configuration.db.xml_mapping.configuration.ResultMap;
import drds.configuration.db.xml_mapping.configuration.ResultMapping;
import drds.tools.$;
import lombok.Getter;
import lombok.Setter;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;

public class DtoMapping {
    @Setter
    @Getter
    private Class clazz;
    @Setter
    @Getter
    private Map<String, Field> columnNameToFieldMap;

    public DtoMapping(Class clazz) {
        this.clazz = clazz;
    }

    public void buildFeildToColumnMapping() {
        //
        ParameterMap parameterMap = new ParameterMap();
        parameterMap.setParameterClass(clazz);
        List<ParameterMapping> parameterMappingList = parameterMap.getParameterMappingList();
        //
        ResultMap resultMap = new ResultMap();
        resultMap.setResultMapClass(clazz);
        List<ResultMapping> resultMappingList = resultMap.getResultMappingList();
        //
        Class superclass = clazz.getSuperclass();
        if (!superclass.equals(Object.class)) {
            throw new IllegalStateException(clazz.getName() + "不能继承其他类");
        }
        Field[] fields = clazz.getDeclaredFields();
        if (!$.isNotNullAndHasElement(fields)) {
            throw new IllegalStateException(clazz.getName() + "没有其他属性");
        }
        Map<String, Field> columnNameToFieldMap = new HashMap<String, Field>();
        for (Field field : fields) {
            // 要求属性必须是private
            if (Modifier.isPrivate(field.getModifiers())) {
                field.setAccessible(true);//在这统一进行初始化
                drds.configuration.db.xml_mapping.annotation.dto.Field dtoField = field.getAnnotation(drds.configuration.db.xml_mapping.annotation.dto.Field.class);
                if (dtoField != null) {
                    String withColumnName = dtoField.withColumnName();
                    if (columnNameToFieldMap.containsKey(withColumnName)) {
                        throw new IllegalStateException(clazz.getName() + "字段:" + field.getName() + "绑定的列名为:" + withColumnName + "重复");
                    }
                    columnNameToFieldMap.put(withColumnName, field);
                    //
                    ParameterMapping parameterMapping = new ParameterMapping();
                    parameterMapping.setPropertyName(field.getName());
                    parameterMapping.setColumnName(withColumnName);
                    parameterMappingList.add(parameterMapping);
                    //
                    ResultMapping resultMapping = new ResultMapping();
                    resultMapping.setPropertyName(field.getName());
                    resultMapping.setColumnName(withColumnName);
                    resultMappingList.add(resultMapping);
                }
            }
        }
        if (!$.isNotNullAndHasElement(columnNameToFieldMap)) {
            throw new IllegalStateException(clazz.getName() + "没有注解的字段");
        }
        this.columnNameToFieldMap = columnNameToFieldMap;
        //
        Set<String> columnNameSet = new HashSet<String>();
        for (Field field : fields) {
            if (Modifier.isPublic(field.getModifiers()) && Modifier.isStatic(field.getModifiers())) {
                field.setAccessible(true);//在这统一进行初始化
                ColumnName columcnNameField = field.getAnnotation(ColumnName.class);
                if (columcnNameField != null) {
                    String value = null;
                    try {
                        value = (String) field.get(clazz);
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                    columnNameSet.add(value);
                }
            }
        }
        //
        for (String columnName : columnNameToFieldMap.keySet()) {
            if (!columnNameSet.contains(columnName)) {
                throw new IllegalStateException("请标记列名注解" + ColumnName.class.getSimpleName() + " of " + columnName);
            }

        }
        //end
        MapperFactory.DtoClassMapping.parameterMapIdToParameterMapMap.put(clazz.getName(), parameterMap);
        MapperFactory.DtoClassMapping.resultMapIdToResultMapMap.put(clazz.getName(), resultMap);
    }
}
